From a3ec773b26759134454cebd4f189f4397edf612c Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 8 Aug 2005 08:18:06 +0000 Subject: [PATCH] Writable pagetables for x86/64. Xen portion. Signed-off-by: Jun Nakajima --- xen/arch/x86/audit.c | 62 ++++---- xen/arch/x86/domain.c | 6 +- xen/arch/x86/mm.c | 234 ++++++++++++++++++++++-------- xen/arch/x86/shadow32.c | 2 +- xen/arch/x86/shadow_public.c | 6 +- xen/arch/x86/traps.c | 11 +- xen/common/grant_table.c | 2 +- xen/include/asm-x86/mm.h | 28 +++- xen/include/asm-x86/page.h | 27 ++-- xen/include/asm-x86/shadow.h | 13 +- xen/include/asm-x86/x86_64/page.h | 3 +- 11 files changed, 269 insertions(+), 125 deletions(-) diff --git a/xen/arch/x86/audit.c b/xen/arch/x86/audit.c index d43db23318..fee6312155 100644 --- a/xen/arch/x86/audit.c +++ b/xen/arch/x86/audit.c @@ -73,7 +73,7 @@ int audit_adjust_pgtables(struct domain *d, int dir, int noisy) if ( tcount < 0 ) { APRINTK("Audit %d: type count went below zero " - "mfn=%lx t=%x ot=%x", + "mfn=%lx t=%" PRtype_info " ot=%x", d->domain_id, page_to_pfn(page), page->u.inuse.type_info, page->tlbflush_timestamp); @@ -82,7 +82,7 @@ int audit_adjust_pgtables(struct domain *d, int dir, int noisy) else if ( (tcount & ~PGT_count_mask) != 0 ) { APRINTK("Audit %d: type count overflowed " - "mfn=%lx t=%x ot=%x", + "mfn=%lx t=%" PRtype_info " ot=%x", d->domain_id, page_to_pfn(page), page->u.inuse.type_info, page->tlbflush_timestamp); @@ -101,7 +101,7 @@ int audit_adjust_pgtables(struct domain *d, int dir, int noisy) if ( count < 0 ) { APRINTK("Audit %d: general count went below zero " - "mfn=%lx t=%x ot=%x", + "mfn=%lx t=%" PRtype_info " ot=%x", d->domain_id, page_to_pfn(page), page->u.inuse.type_info, page->tlbflush_timestamp); @@ -110,7 +110,7 @@ int audit_adjust_pgtables(struct domain *d, int dir, int noisy) else if ( (count & ~PGT_count_mask) != 0 ) { APRINTK("Audit %d: general count overflowed " - "mfn=%lx t=%x ot=%x", + "mfn=%lx t=%" PRtype_info " ot=%x", d->domain_id, page_to_pfn(page), page->u.inuse.type_info, page->tlbflush_timestamp); @@ -152,7 +152,8 @@ int audit_adjust_pgtables(struct domain *d, int dir, int noisy) if ( page_type != PGT_l1_shadow ) { printk("Audit %d: [Shadow L2 mfn=%lx i=%x] " - "Expected Shadow L1 t=%x mfn=%lx\n", + "Expected Shadow L1 t=%" PRtype_info + " mfn=%lx\n", d->domain_id, mfn, i, l1page->u.inuse.type_info, l1mfn); errors++; @@ -178,14 +179,14 @@ int audit_adjust_pgtables(struct domain *d, int dir, int noisy) if ( page_type == PGT_l2_page_table ) { printk("Audit %d: [%x] Found %s Linear PT " - "t=%x mfn=%lx\n", + "t=%" PRtype_info " mfn=%lx\n", d->domain_id, i, (l1mfn==mfn) ? "Self" : "Other", l1page->u.inuse.type_info, l1mfn); } else if ( page_type != PGT_l1_page_table ) { printk("Audit %d: [L2 mfn=%lx i=%x] " - "Expected L1 t=%x mfn=%lx\n", + "Expected L1 t=%" PRtype_info " mfn=%lx\n", d->domain_id, mfn, i, l1page->u.inuse.type_info, l1mfn); errors++; @@ -237,7 +238,8 @@ int audit_adjust_pgtables(struct domain *d, int dir, int noisy) if ( page_get_owner(gpage) != d ) { printk("Audit %d: [hl2mfn=%lx,i=%x] Skip foreign page " - "dom=%p (id=%d) mfn=%lx c=%08x t=%08x\n", + "dom=%p (id=%d) mfn=%lx c=%08x t=%" + PRtype_info "\n", d->domain_id, hl2mfn, i, page_get_owner(gpage), page_get_owner(gpage)->domain_id, @@ -288,7 +290,7 @@ int audit_adjust_pgtables(struct domain *d, int dir, int noisy) PGT_writable_page) ) { printk("Audit %d: [l1mfn=%lx, i=%x] Illegal RW " - "t=%x mfn=%lx\n", + "t=%" PRtype_info " mfn=%lx\n", d->domain_id, l1mfn, i, gpage->u.inuse.type_info, gmfn); errors++; @@ -308,7 +310,8 @@ int audit_adjust_pgtables(struct domain *d, int dir, int noisy) if ( page_get_owner(gpage) != d ) { printk("Audit %d: [l1mfn=%lx,i=%x] Skip foreign page " - "dom=%p (id=%d) mfn=%lx c=%08x t=%08x\n", + "dom=%p (id=%d) mfn=%lx c=%08x t=%" + PRtype_info "\n", d->domain_id, l1mfn, i, page_get_owner(gpage), page_get_owner(gpage)->domain_id, @@ -454,7 +457,7 @@ int audit_adjust_pgtables(struct domain *d, int dir, int noisy) if ( shadow_refcounts ) { printk("Audit %d: found an L2 guest page " - "mfn=%lx t=%08x c=%08x while in shadow mode\n", + "mfn=%lx t=%" PRtype_info " c=%08x while in shadow mode\n", d->domain_id, mfn, page->u.inuse.type_info, page->count_info); errors++; @@ -465,14 +468,16 @@ int audit_adjust_pgtables(struct domain *d, int dir, int noisy) if ( (page->u.inuse.type_info & PGT_validated) != PGT_validated ) { - printk("Audit %d: L2 mfn=%lx not validated %08x\n", + printk("Audit %d: L2 mfn=%lx not validated %" + PRtype_info "\n", d->domain_id, mfn, page->u.inuse.type_info); errors++; } if ( (page->u.inuse.type_info & PGT_pinned) != PGT_pinned ) { - printk("Audit %d: L2 mfn=%lx not pinned t=%08x\n", + printk("Audit %d: L2 mfn=%lx not pinned t=%" + PRtype_info "\n", d->domain_id, mfn, page->u.inuse.type_info); errors++; } @@ -494,7 +499,8 @@ int audit_adjust_pgtables(struct domain *d, int dir, int noisy) { if ( shadow_refcounts ) { - printk("found an L1 guest page mfn=%lx t=%08x c=%08x " + printk("found an L1 guest page mfn=%lx t=%" + PRtype_info " c=%08x " "while in shadow mode\n", mfn, page->u.inuse.type_info, page->count_info); errors++; @@ -505,7 +511,8 @@ int audit_adjust_pgtables(struct domain *d, int dir, int noisy) if ( (page->u.inuse.type_info & PGT_validated) != PGT_validated ) { - printk("Audit %d: L1 not validated mfn=%lx t=%08x\n", + printk("Audit %d: L1 not validated mfn=%lx t=%" + PRtype_info "\n", d->domain_id, mfn, page->u.inuse.type_info); errors++; } @@ -514,7 +521,8 @@ int audit_adjust_pgtables(struct domain *d, int dir, int noisy) { if ( !VM_ASSIST(d, VMASST_TYPE_writable_pagetables) ) { - printk("Audit %d: L1 mfn=%lx not pinned t=%08x\n", + printk("Audit %d: L1 mfn=%lx not pinned t=%" + PRtype_info "\n", d->domain_id, mfn, page->u.inuse.type_info); } } @@ -621,7 +629,7 @@ void _audit_domain(struct domain *d, int flags) for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ ) { if ( (pt[i] & _PAGE_PRESENT) && ((pt[i] >> PAGE_SHIFT) == xmfn) ) - printk(" found dom=%d mfn=%lx t=%08x c=%08x " + printk(" found dom=%d mfn=%lx t=%" PRtype_info " c=%08x " "pt[i=%x]=%lx\n", d->domain_id, mfn, page->u.inuse.type_info, page->count_info, i, pt[i]); @@ -754,7 +762,7 @@ void _audit_domain(struct domain *d, int flags) if ( (page->u.inuse.type_info & PGT_count_mask) > (page->count_info & PGC_count_mask) ) { - printk("taf(%08x) > caf(%08x) mfn=%lx\n", + printk("taf(%" PRtype_info ") > caf(%08x) mfn=%lx\n", page->u.inuse.type_info, page->count_info, mfn); errors++; } @@ -763,8 +771,8 @@ void _audit_domain(struct domain *d, int flags) (page_type == PGT_writable_page) && !(page->u.inuse.type_info & PGT_validated) ) { - printk("shadow mode writable page not validated mfn=%lx " - "t=%08x c=%08x\n", + printk("shadow mode writable page not validated mfn=%lx " + "t=%" PRtype_info " c=%08x\n", mfn, page->u.inuse.type_info, page->count_info); errors++; } @@ -774,7 +782,7 @@ void _audit_domain(struct domain *d, int flags) (page->u.inuse.type_info & PGT_count_mask) > 1 ) { printk("writeable page with type count >1: " - "mfn=%lx t=%08x c=%08x\n", + "mfn=%lx t=%" PRtype_info " c=%08x\n", mfn, page->u.inuse.type_info, page->count_info ); @@ -786,7 +794,7 @@ void _audit_domain(struct domain *d, int flags) if ( page_type == PGT_none && (page->u.inuse.type_info & PGT_count_mask) > 0 ) { - printk("normal page with type count >0: mfn=%lx t=%08x c=%08x\n", + printk("normal page with type count >0: mfn=%lx t=%" PRtype_info " c=%08x\n", mfn, page->u.inuse.type_info, page->count_info ); @@ -812,7 +820,7 @@ void _audit_domain(struct domain *d, int flags) : !(page_type && (page_type <= PGT_l4_page_table)) ) { printk("out of sync page mfn=%lx has strange type " - "t=%08x c=%08x\n", + "t=%" PRtype_info " c=%08x\n", mfn, page->u.inuse.type_info, page->count_info); errors++; } @@ -850,7 +858,7 @@ void _audit_domain(struct domain *d, int flags) case PGT_l4_page_table: if ( (page->u.inuse.type_info & PGT_count_mask) != 0 ) { - printk("Audit %d: type count!=0 t=%x ot=%x c=%x mfn=%lx\n", + printk("Audit %d: type count!=0 t=%" PRtype_info " ot=%x c=%x mfn=%lx\n", d->domain_id, page->u.inuse.type_info, page->tlbflush_timestamp, page->count_info, mfn); @@ -864,7 +872,7 @@ void _audit_domain(struct domain *d, int flags) case PGT_ldt_page: if ( (page->u.inuse.type_info & PGT_count_mask) != 0 ) { - printk("Audit %d: type count!=0 t=%x ot=%x c=%x mfn=%lx\n", + printk("Audit %d: type count!=0 t=%" PRtype_info " ot=%x c=%x mfn=%lx\n", d->domain_id, page->u.inuse.type_info, page->tlbflush_timestamp, page->count_info, mfn); @@ -877,7 +885,7 @@ void _audit_domain(struct domain *d, int flags) if ( (page->count_info & PGC_count_mask) != 1 ) { - printk("Audit %d: gen count!=1 (c=%x) t=%x ot=%x mfn=%lx\n", + printk("Audit %d: gen count!=1 (c=%x) t=%" PRtype_info " ot=%x mfn=%lx\n", d->domain_id, page->count_info, page->u.inuse.type_info, @@ -913,7 +921,7 @@ void _audit_domain(struct domain *d, int flags) (page->count_info != 0) ) { printk("Audit %d: shadow page counts wrong " - "mfn=%lx t=%08x c=%08x\n", + "mfn=%lx t=%" PRtype_info " c=%08x\n", d->domain_id, page_to_pfn(page), page->u.inuse.type_info, page->count_info); diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index a8c33c0e07..dedebbbd6c 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -190,7 +190,7 @@ void dump_pageframe_info(struct domain *d) { list_for_each_entry ( page, &d->page_list, list ) { - printk("Page %p: caf=%08x, taf=%08x\n", + printk("Page %p: caf=%08x, taf=%" PRtype_info "\n", _p(page_to_phys(page)), page->count_info, page->u.inuse.type_info); } @@ -198,14 +198,14 @@ void dump_pageframe_info(struct domain *d) list_for_each_entry ( page, &d->xenpage_list, list ) { - printk("XenPage %p: caf=%08x, taf=%08x\n", + printk("XenPage %p: caf=%08x, taf=%" PRtype_info "\n", _p(page_to_phys(page)), page->count_info, page->u.inuse.type_info); } page = virt_to_page(d->shared_info); - printk("Shared_info@%p: caf=%08x, taf=%08x\n", + printk("Shared_info@%p: caf=%08x, taf=%" PRtype_info "\n", _p(page_to_phys(page)), page->count_info, page->u.inuse.type_info); } diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 0734c50847..4a934b090e 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -122,7 +122,7 @@ static void free_l2_table(struct pfn_info *page); static void free_l1_table(struct pfn_info *page); static int mod_l2_entry(l2_pgentry_t *, l2_pgentry_t, unsigned long, - unsigned int type); + unsigned long type); static int mod_l1_entry(l1_pgentry_t *, l1_pgentry_t); /* Used to defer flushing of memory structures. */ @@ -354,7 +354,7 @@ static int get_page_from_pagenr(unsigned long page_nr, struct domain *d) static int get_page_and_type_from_pagenr(unsigned long page_nr, - u32 type, + unsigned long type, struct domain *d) { struct pfn_info *page = &frame_table[page_nr]; @@ -365,7 +365,7 @@ static int get_page_and_type_from_pagenr(unsigned long page_nr, if ( unlikely(!get_page_type(page, type)) ) { if ( (type & PGT_type_mask) != PGT_l1_page_table ) - MEM_LOG("Bad page type for pfn %lx (%08x)", + MEM_LOG("Bad page type for pfn %lx (%" PRtype_info ")", page_nr, page->u.inuse.type_info); put_page(page); return 0; @@ -390,7 +390,7 @@ static int get_linear_pagetable( root_pgentry_t re, unsigned long re_pfn, struct domain *d) { - u32 x, y; + unsigned long x, y; struct pfn_info *page; unsigned long pfn; @@ -544,7 +544,8 @@ get_page_from_l3e( static int get_page_from_l4e( - l4_pgentry_t l4e, unsigned long pfn, struct domain *d) + l4_pgentry_t l4e, unsigned long pfn, + struct domain *d, unsigned long vaddr) { int rc; @@ -559,8 +560,11 @@ get_page_from_l4e( return 0; } + vaddr >>= L4_PAGETABLE_SHIFT; + vaddr <<= PGT_va_shift; rc = get_page_and_type_from_pagenr( - l4e_get_pfn(l4e), PGT_l3_page_table, d); + l4e_get_pfn(l4e), + PGT_l3_page_table | vaddr, d); if ( unlikely(!rc) ) return get_linear_pagetable(l4e, pfn, d); @@ -750,13 +754,47 @@ static inline int l1_backptr( return 1; } +#elif CONFIG_X86_64 +# define create_pae_xen_mappings(pl3e) (1) + +static inline int l1_backptr( + unsigned long *backptr, unsigned long offset_in_l2, unsigned long l2_type) +{ + unsigned long l2_backptr = l2_type & PGT_va_mask; + BUG_ON(l2_backptr == PGT_va_unknown); + + *backptr = ((l2_backptr >> PGT_va_shift) << L3_PAGETABLE_SHIFT) | + (offset_in_l2 << L2_PAGETABLE_SHIFT); + return 1; +} + +static inline int l2_backptr( + unsigned long *backptr, unsigned long offset_in_l3, unsigned long l3_type) +{ + unsigned long l3_backptr = l3_type & PGT_va_mask; + BUG_ON(l3_backptr == PGT_va_unknown); + + *backptr = ((l3_backptr >> PGT_va_shift) << L4_PAGETABLE_SHIFT) | + (offset_in_l3 << L3_PAGETABLE_SHIFT); + return 1; +} + +static inline int l3_backptr( + unsigned long *backptr, unsigned long offset_in_l4, unsigned long l4_type) +{ + unsigned long l4_backptr = l4_type & PGT_va_mask; + BUG_ON(l4_backptr == PGT_va_unknown); + + *backptr = (offset_in_l4 << L4_PAGETABLE_SHIFT); + return 1; +} #else # define create_pae_xen_mappings(pl3e) (1) # define l1_backptr(bp,l2o,l2t) \ ({ *(bp) = (unsigned long)(l2o) << L2_PAGETABLE_SHIFT; 1; }) #endif -static int alloc_l2_table(struct pfn_info *page, unsigned int type) +static int alloc_l2_table(struct pfn_info *page, unsigned long type) { struct domain *d = page_get_owner(page); unsigned long pfn = page_to_pfn(page); @@ -808,7 +846,7 @@ static int alloc_l2_table(struct pfn_info *page, unsigned int type) #if CONFIG_PAGING_LEVELS >= 3 -static int alloc_l3_table(struct pfn_info *page) +static int alloc_l3_table(struct pfn_info *page, unsigned long type) { struct domain *d = page_get_owner(page); unsigned long pfn = page_to_pfn(page); @@ -821,7 +859,12 @@ static int alloc_l3_table(struct pfn_info *page) pl3e = map_domain_page(pfn); for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ ) { - vaddr = (unsigned long)i << L3_PAGETABLE_SHIFT; +#if CONFIG_PAGING_LEVELS >= 4 + if ( !l2_backptr(&vaddr, i, type) ) + goto fail; +#else + vaddr = (unsigned long)i << L3_PAGETABLE_SHIFT; +#endif if ( is_guest_l3_slot(i) && unlikely(!get_page_from_l3e(pl3e[i], pfn, d, vaddr)) ) goto fail; @@ -842,15 +885,16 @@ static int alloc_l3_table(struct pfn_info *page) return 0; } #else -#define alloc_l3_table(page) (0) +#define alloc_l3_table(page, type) (0) #endif #if CONFIG_PAGING_LEVELS >= 4 -static int alloc_l4_table(struct pfn_info *page) +static int alloc_l4_table(struct pfn_info *page, unsigned long type) { struct domain *d = page_get_owner(page); unsigned long pfn = page_to_pfn(page); l4_pgentry_t *pl4e = page_to_virt(page); + unsigned long vaddr; int i; /* See the code in shadow_promote() to understand why this is here. */ @@ -859,10 +903,14 @@ static int alloc_l4_table(struct pfn_info *page) return 1; ASSERT(!shadow_mode_refcounts(d)); - for ( i = 0; i < L4_PAGETABLE_ENTRIES; i++ ) + for ( i = 0; i < L4_PAGETABLE_ENTRIES; i++ ) { + if ( !l3_backptr(&vaddr, i, type) ) + goto fail; + if ( is_guest_l4_slot(i) && - unlikely(!get_page_from_l4e(pl4e[i], pfn, d)) ) + unlikely(!get_page_from_l4e(pl4e[i], pfn, d, vaddr)) ) goto fail; + } /* Xen private mappings. */ memcpy(&pl4e[ROOT_PAGETABLE_FIRST_XEN_SLOT], @@ -885,7 +933,7 @@ static int alloc_l4_table(struct pfn_info *page) return 0; } #else -#define alloc_l4_table(page) (0) +#define alloc_l4_table(page, type) (0) #endif @@ -1037,7 +1085,7 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e) static int mod_l2_entry(l2_pgentry_t *pl2e, l2_pgentry_t nl2e, unsigned long pfn, - unsigned int type) + unsigned long type) { l2_pgentry_t ol2e; unsigned long vaddr = 0; @@ -1090,7 +1138,8 @@ static int mod_l2_entry(l2_pgentry_t *pl2e, /* Update the L3 entry at pl3e to new value nl3e. pl3e is within frame pfn. */ static int mod_l3_entry(l3_pgentry_t *pl3e, l3_pgentry_t nl3e, - unsigned long pfn) + unsigned long pfn, + unsigned long type) { l3_pgentry_t ol3e; unsigned long vaddr; @@ -1126,10 +1175,16 @@ static int mod_l3_entry(l3_pgentry_t *pl3e, if (!l3e_has_changed(ol3e, nl3e, _PAGE_PRESENT)) return UPDATE_ENTRY(l3, pl3e, ol3e, nl3e); +#if CONFIG_PAGING_LEVELS >= 4 + if ( unlikely(!l2_backptr(&vaddr, pgentry_ptr_to_slot(pl3e), type)) || + unlikely(!get_page_from_l3e(nl3e, pfn, current->domain, vaddr)) ) + return 0; +#else vaddr = (((unsigned long)pl3e & ~PAGE_MASK) / sizeof(l3_pgentry_t)) << L3_PAGETABLE_SHIFT; if ( unlikely(!get_page_from_l3e(nl3e, pfn, current->domain, vaddr)) ) return 0; +#endif if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e)) ) { @@ -1141,12 +1196,14 @@ static int mod_l3_entry(l3_pgentry_t *pl3e, put_page_from_l3e(ol3e, pfn); return 1; } - - if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e)) ) - { - BUG_ON(!create_pae_xen_mappings(pl3e)); - return 0; - } + else + { + if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e)) ) + { + BUG_ON(!create_pae_xen_mappings(pl3e)); + return 0; + } + } put_page_from_l3e(ol3e, pfn); return 1; @@ -1159,9 +1216,11 @@ static int mod_l3_entry(l3_pgentry_t *pl3e, /* Update the L4 entry at pl4e to new value nl4e. pl4e is within frame pfn. */ static int mod_l4_entry(l4_pgentry_t *pl4e, l4_pgentry_t nl4e, - unsigned long pfn) + unsigned long pfn, + unsigned long type) { l4_pgentry_t ol4e; + unsigned long vaddr; if ( unlikely(!is_guest_l4_slot(pgentry_ptr_to_slot(pl4e))) ) { @@ -1185,7 +1244,8 @@ static int mod_l4_entry(l4_pgentry_t *pl4e, if (!l4e_has_changed(ol4e, nl4e, _PAGE_PRESENT)) return UPDATE_ENTRY(l4, pl4e, ol4e, nl4e); - if ( unlikely(!get_page_from_l4e(nl4e, pfn, current->domain)) ) + if ( unlikely(!l3_backptr(&vaddr, pgentry_ptr_to_slot(pl4e), type)) || + unlikely(!get_page_from_l4e(nl4e, pfn, current->domain, vaddr)) ) return 0; if ( unlikely(!UPDATE_ENTRY(l4, pl4e, ol4e, nl4e)) ) @@ -1193,13 +1253,12 @@ static int mod_l4_entry(l4_pgentry_t *pl4e, put_page_from_l4e(nl4e, pfn); return 0; } - - put_page_from_l4e(ol4e, pfn); - return 1; } - - if ( unlikely(!UPDATE_ENTRY(l4, pl4e, ol4e, nl4e)) ) - return 0; + else + { + if ( unlikely(!UPDATE_ENTRY(l4, pl4e, ol4e, nl4e)) ) + return 0; + } put_page_from_l4e(ol4e, pfn); return 1; @@ -1207,7 +1266,7 @@ static int mod_l4_entry(l4_pgentry_t *pl4e, #endif -int alloc_page_type(struct pfn_info *page, unsigned int type) +int alloc_page_type(struct pfn_info *page, unsigned long type) { switch ( type & PGT_type_mask ) { @@ -1216,14 +1275,14 @@ int alloc_page_type(struct pfn_info *page, unsigned int type) case PGT_l2_page_table: return alloc_l2_table(page, type); case PGT_l3_page_table: - return alloc_l3_table(page); + return alloc_l3_table(page, type); case PGT_l4_page_table: - return alloc_l4_table(page); + return alloc_l4_table(page, type); case PGT_gdt_page: case PGT_ldt_page: return alloc_segdesc_page(page); default: - printk("Bad type in alloc_page_type %x t=%x c=%x\n", + printk("Bad type in alloc_page_type %lx t=%" PRtype_info " c=%x\n", type, page->u.inuse.type_info, page->count_info); BUG(); @@ -1233,7 +1292,7 @@ int alloc_page_type(struct pfn_info *page, unsigned int type) } -void free_page_type(struct pfn_info *page, unsigned int type) +void free_page_type(struct pfn_info *page, unsigned long type) { struct domain *owner = page_get_owner(page); unsigned long gpfn; @@ -1273,7 +1332,7 @@ void free_page_type(struct pfn_info *page, unsigned int type) #endif default: - printk("%s: type %x pfn %lx\n",__FUNCTION__, + printk("%s: type %lx pfn %lx\n",__FUNCTION__, type, page_to_pfn(page)); BUG(); } @@ -1282,7 +1341,7 @@ void free_page_type(struct pfn_info *page, unsigned int type) void put_page_type(struct pfn_info *page) { - u32 nx, x, y = page->u.inuse.type_info; + unsigned long nx, x, y = page->u.inuse.type_info; again: do { @@ -1335,9 +1394,9 @@ void put_page_type(struct pfn_info *page) } -int get_page_type(struct pfn_info *page, u32 type) +int get_page_type(struct pfn_info *page, unsigned long type) { - u32 nx, x, y = page->u.inuse.type_info; + unsigned long nx, x, y = page->u.inuse.type_info; again: do { @@ -1350,7 +1409,11 @@ int get_page_type(struct pfn_info *page, u32 type) } else if ( unlikely((x & PGT_count_mask) == 0) ) { +#ifdef CONFIG_X86_64 + if ( (x & (PGT_type_mask|PGT_va_mask)) != (type & ~PGT_va_mask)) +#else if ( (x & (PGT_type_mask|PGT_va_mask)) != type ) +#endif { if ( (x & PGT_type_mask) != (type & PGT_type_mask) ) { @@ -1382,13 +1445,17 @@ int get_page_type(struct pfn_info *page, u32 type) } else { +#ifdef CONFIG_X86_64 + if ( unlikely((x & (PGT_type_mask|PGT_va_mask)) != (type & ~PGT_va_mask)) ) +#else if ( unlikely((x & (PGT_type_mask|PGT_va_mask)) != type) ) +#endif { if ( unlikely((x & PGT_type_mask) != (type & PGT_type_mask) ) ) { if ( ((x & PGT_type_mask) != PGT_l2_page_table) || ((type & PGT_type_mask) != PGT_l1_page_table) ) - MEM_LOG("Bad type (saw %08x != exp %08x) for pfn %lx", + MEM_LOG("Bad type (saw %" PRtype_info "!= exp %" PRtype_info ") for pfn %lx", x, type, page_to_pfn(page)); return 0; } @@ -1427,8 +1494,8 @@ int get_page_type(struct pfn_info *page, u32 type) /* Try to validate page type; drop the new reference on failure. */ if ( unlikely(!alloc_page_type(page, type)) ) { - MEM_LOG("Error while validating pfn %lx for type %08x." - " caf=%08x taf=%08x", + MEM_LOG("Error while validating pfn %lx for type %" PRtype_info "." + " caf=%08x taf=%" PRtype_info, page_to_pfn(page), type, page->count_info, page->u.inuse.type_info); @@ -1596,7 +1663,7 @@ int do_mmuext_op( { struct mmuext_op op; int rc = 0, i = 0, okay, cpu = smp_processor_id(); - unsigned int type, done = 0; + unsigned long type, done = 0; struct pfn_info *page; struct vcpu *v = current; struct domain *d = v->domain, *e; @@ -1651,6 +1718,9 @@ int do_mmuext_op( type = PGT_l1_page_table | PGT_va_mutable; pin_page: +#if CONFIG_PAGING_LEVELS >= 4 + type |= PGT_va_mutable; +#endif if ( shadow_mode_refcounts(FOREIGNDOM) ) type = PGT_writable_page; @@ -1876,7 +1946,7 @@ int do_mmuext_op( unlikely(_nd != _d) ) { MEM_LOG("Bad page values %lx: ed=%p(%u), sd=%p," - " caf=%08x, taf=%08x\n", page_to_pfn(page), + " caf=%08x, taf=%" PRtype_info "\n", page_to_pfn(page), d, d->domain_id, unpickle_domptr(_nd), x, page->u.inuse.type_info); okay = 0; @@ -1951,7 +2021,7 @@ int do_mmu_update( unsigned int cmd, done = 0; struct vcpu *v = current; struct domain *d = v->domain; - u32 type_info; + unsigned long type_info; struct domain_mmap_cache mapcache, sh_mapcache; LOCK_BIGLOCK(d); @@ -2063,13 +2133,14 @@ int do_mmu_update( #if CONFIG_PAGING_LEVELS >= 3 case PGT_l3_page_table: ASSERT( !shadow_mode_refcounts(d) ); - if ( likely(get_page_type(page, PGT_l3_page_table)) ) + if ( likely(get_page_type( + page, type_info & (PGT_type_mask|PGT_va_mask))) ) { l3_pgentry_t l3e; /* FIXME: doesn't work with PAE */ l3e = l3e_from_intpte(req.val); - okay = mod_l3_entry(va, l3e, mfn); + okay = mod_l3_entry(va, l3e, mfn, type_info); if ( okay && unlikely(shadow_mode_enabled(d)) ) shadow_l3_normal_pt_update(d, req.ptr, l3e, &sh_mapcache); put_page_type(page); @@ -2079,12 +2150,13 @@ int do_mmu_update( #if CONFIG_PAGING_LEVELS >= 4 case PGT_l4_page_table: ASSERT( !shadow_mode_refcounts(d) ); - if ( likely(get_page_type(page, PGT_l4_page_table)) ) + if ( likely(get_page_type( + page, type_info & (PGT_type_mask|PGT_va_mask))) ) { l4_pgentry_t l4e; l4e = l4e_from_intpte(req.val); - okay = mod_l4_entry(va, l4e, mfn); + okay = mod_l4_entry(va, l4e, mfn, type_info); if ( okay && unlikely(shadow_mode_enabled(d)) ) shadow_l4_normal_pt_update(d, req.ptr, l4e, &sh_mapcache); put_page_type(page); @@ -2618,11 +2690,19 @@ void ptwr_flush(struct domain *d, const int which) l1_pgentry_t *pl1e; l2_pgentry_t *pl2e; unsigned int modified; +#if defined(__x86_64__) + struct vcpu *v = current; + /* If in user mode, switch to kernel mode just to read LDT mapping. */ + extern void toggle_guest_mode(struct vcpu *); + int user_mode = !(v->arch.flags & TF_kernel_mode); +#endif ASSERT(!shadow_mode_enabled(d)); if ( unlikely(d->arch.ptwr[which].vcpu != current) ) write_ptbase(d->arch.ptwr[which].vcpu); + else + TOGGLE_MODE(); l1va = d->arch.ptwr[which].l1va; ptep = (unsigned long *)&linear_pg_table[l1_linear_offset(l1va)]; @@ -2689,6 +2769,8 @@ void ptwr_flush(struct domain *d, const int which) if ( unlikely(d->arch.ptwr[which].vcpu != current) ) write_ptbase(current); + else + TOGGLE_MODE(); } static int ptwr_emulated_update( @@ -2747,7 +2829,7 @@ static int ptwr_emulated_update( ((page->u.inuse.type_info & PGT_type_mask) != PGT_l1_page_table) || (page_get_owner(page) != d) ) { - MEM_LOG("ptwr_emulate: Page is mistyped or bad pte (%lx, %08x)\n", + MEM_LOG("ptwr_emulate: Page is mistyped or bad pte (%lx, %" PRtype_info ")\n", l1e_get_pfn(pte), page->u.inuse.type_info); return X86EMUL_UNHANDLEABLE; } @@ -2820,6 +2902,35 @@ static struct x86_mem_emulator ptwr_mem_emulator = { .cmpxchg8b_emulated = ptwr_emulated_cmpxchg8b }; +#if defined(__x86_64__) +/* + * Returns zero on if mapped, or -1 otherwise + */ +static int __not_mapped(l2_pgentry_t *pl2e) +{ + unsigned long page = read_cr3(); + + page &= PAGE_MASK; + page = ((unsigned long *) __va(page))[l4_table_offset((unsigned long)pl2e)]; + if ( !(page & _PAGE_PRESENT) ) + return -1; + + page &= PAGE_MASK; + page = ((unsigned long *) __va(page))[l3_table_offset((unsigned long)pl2e)]; + if ( !(page & _PAGE_PRESENT) ) + return -1; + + page &= PAGE_MASK; + page = ((unsigned long *) __va(page))[l2_table_offset((unsigned long)pl2e)]; + if ( !(page & _PAGE_PRESENT) ) + return -1; + + return 0; +} +#else +#define __not_mapped(p) (0) +#endif + /* Write page fault handler: check if guest is trying to modify a PTE. */ int ptwr_do_page_fault(struct domain *d, unsigned long addr) { @@ -2828,7 +2939,7 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr) l1_pgentry_t pte; l2_pgentry_t *pl2e; int which; - u32 l2_idx; + unsigned long l2_idx; if ( unlikely(shadow_mode_enabled(d)) ) return 0; @@ -2837,7 +2948,7 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr) * Attempt to read the PTE that maps the VA being accessed. By checking for * PDE validity in the L2 we avoid many expensive fixups in __get_user(). */ - if ( !(l2e_get_flags(__linear_l2_table[addr>>L2_PAGETABLE_SHIFT]) & + if ( !(l2e_get_flags(__linear_l2_table[l2_linear_offset(addr)]) & _PAGE_PRESENT) || __copy_from_user(&pte,&linear_pg_table[l1_linear_offset(addr)], sizeof(pte)) ) @@ -2857,18 +2968,13 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr) return 0; } - /* x86/64: Writable pagetable code needs auditing. Use emulator for now. */ -#if defined(__x86_64__) - goto emulate; -#endif - /* Get the L2 index at which this L1 p.t. is always mapped. */ l2_idx = page->u.inuse.type_info & PGT_va_mask; if ( unlikely(l2_idx >= PGT_va_unknown) ) goto emulate; /* Urk! This L1 is mapped in multiple L2 slots! */ l2_idx >>= PGT_va_shift; - if ( unlikely(l2_idx == (addr >> L2_PAGETABLE_SHIFT)) ) + if ( unlikely(l2_idx == l2_linear_offset(addr)) ) goto emulate; /* Urk! Pagetable maps itself! */ /* @@ -2877,6 +2983,10 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr) */ pl2e = &__linear_l2_table[l2_idx]; which = PTWR_PT_INACTIVE; + + if ( unlikely(__not_mapped(pl2e)) ) + goto inactive; + if ( (l2e_get_pfn(*pl2e)) == pfn ) { /* @@ -2891,6 +3001,8 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr) which = PTWR_PT_ACTIVE; } + inactive: + /* * If this is a multi-processor guest then ensure that the page is hooked * into at most one L2 table, which must be the one running on this VCPU. @@ -2905,7 +3017,7 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr) goto emulate; } - PTWR_PRINTK("[%c] page_fault on l1 pt at va %lx, pt for %08x, " + PTWR_PRINTK("[%c] page_fault on l1 pt at va %lx, pt for %08lx, " "pfn %lx\n", PTWR_PRINT_WHICH, addr, l2_idx << L2_PAGETABLE_SHIFT, pfn); @@ -2946,11 +3058,11 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr) /* Finally, make the p.t. page writable by the guest OS. */ l1e_add_flags(pte, _PAGE_RW); - if ( unlikely(__copy_to_user(&linear_pg_table[addr>>PAGE_SHIFT], + if ( unlikely(__copy_to_user(&linear_pg_table[l1_linear_offset(addr)], &pte, sizeof(pte))) ) { MEM_LOG("ptwr: Could not update pte at %p", (unsigned long *) - &linear_pg_table[addr>>PAGE_SHIFT]); + &linear_pg_table[l1_linear_offset(addr)]); /* Toss the writable pagetable state and crash. */ unmap_domain_page(d->arch.ptwr[which].pl1e); d->arch.ptwr[which].l1va = 0; diff --git a/xen/arch/x86/shadow32.c b/xen/arch/x86/shadow32.c index 0c0f749401..de7656e674 100644 --- a/xen/arch/x86/shadow32.c +++ b/xen/arch/x86/shadow32.c @@ -418,7 +418,7 @@ void free_shadow_page(unsigned long smfn) break; default: - printk("Free shadow weird page type mfn=%lx type=%08x\n", + printk("Free shadow weird page type mfn=%lx type=%" PRtype_info "\n", page_to_pfn(page), page->u.inuse.type_info); break; } diff --git a/xen/arch/x86/shadow_public.c b/xen/arch/x86/shadow_public.c index c905a7f9cc..88cd5fcd51 100644 --- a/xen/arch/x86/shadow_public.c +++ b/xen/arch/x86/shadow_public.c @@ -571,7 +571,7 @@ void free_shadow_page(unsigned long smfn) break; default: - printk("Free shadow weird page type mfn=%lx type=%08x\n", + printk("Free shadow weird page type mfn=%lx type=%" PRtype_info "\n", page_to_pfn(page), page->u.inuse.type_info); break; } @@ -1638,14 +1638,14 @@ void shadow_drop_references( /* XXX This needs more thought... */ printk("%s: needing to call __shadow_remove_all_access for mfn=%lx\n", __func__, page_to_pfn(page)); - printk("Before: mfn=%lx c=%08x t=%08x\n", page_to_pfn(page), + printk("Before: mfn=%lx c=%08x t=%" PRtype_info "\n", page_to_pfn(page), page->count_info, page->u.inuse.type_info); shadow_lock(d); __shadow_remove_all_access(d, page_to_pfn(page)); shadow_unlock(d); - printk("After: mfn=%lx c=%08x t=%08x\n", page_to_pfn(page), + printk("After: mfn=%lx c=%08x t=%" PRtype_info "\n", page_to_pfn(page), page->count_info, page->u.inuse.type_info); } diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index b038c37b22..d3878cb1b8 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -422,7 +422,7 @@ asmlinkage int do_page_fault(struct cpu_user_regs *regs) { LOCK_BIGLOCK(d); if ( unlikely(d->arch.ptwr[PTWR_PT_ACTIVE].l1va) && - unlikely((addr >> L2_PAGETABLE_SHIFT) == + unlikely(l2_linear_offset(addr) == d->arch.ptwr[PTWR_PT_ACTIVE].l2_idx) ) { ptwr_flush(d, PTWR_PT_ACTIVE); @@ -430,7 +430,12 @@ asmlinkage int do_page_fault(struct cpu_user_regs *regs) return EXCRET_fault_fixed; } - if ( (addr < HYPERVISOR_VIRT_START) && + if ( ((addr < HYPERVISOR_VIRT_START) +#if defined(__x86_64__) + || (addr >= HYPERVISOR_VIRT_END) +#endif + ) + && KERNEL_MODE(v, regs) && ((regs->error_code & 3) == 3) && /* write-protection fault */ ptwr_do_page_fault(d, addr) ) @@ -459,7 +464,7 @@ asmlinkage int do_page_fault(struct cpu_user_regs *regs) goto xen_fault; propagate_page_fault(addr, regs->error_code); - return 0; + return 0; xen_fault: diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index 40d1cab4dd..03f9c8dd6a 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -859,7 +859,7 @@ gnttab_donate(gnttab_donate_t *uop, unsigned int count) if (unlikely((x & (PGC_count_mask|PGC_allocated)) != (1 | PGC_allocated)) || unlikely(_nd != _d)) { printk("gnttab_donate: Bad page values %p: ed=%p(%u), sd=%p," - " caf=%08x, taf=%08x\n", (void *) page_to_pfn(page), + " caf=%08x, taf=%" PRtype_info "\n", (void *) page_to_pfn(page), d, d->domain_id, unpickle_domptr(_nd), x, page->u.inuse.type_info); spin_unlock(&d->page_alloc_lock); diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index 4484b59fcd..f50b4d8028 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -36,7 +36,7 @@ struct pfn_info /* Owner of this page (NULL if page is anonymous). */ u32 _domain; /* pickled format */ /* Type reference count and various PGT_xxx flags and fields. */ - u32 type_info; + unsigned long type_info; } inuse; /* Page is on a free list: ((count_info & PGC_count_mask) == 0). */ @@ -77,6 +77,7 @@ struct pfn_info /* Owning guest has pinned this page to its current type? */ #define _PGT_pinned 27 #define PGT_pinned (1U<<_PGT_pinned) +#if defined(__i386__) /* The 11 most significant bits of virt address if this is a page table. */ #define PGT_va_shift 16 #define PGT_va_mask (((1U<<11)-1)<u.inuse._domain)) @@ -144,8 +160,8 @@ extern struct pfn_info *frame_table; extern unsigned long max_page; void init_frametable(void); -int alloc_page_type(struct pfn_info *page, unsigned int type); -void free_page_type(struct pfn_info *page, unsigned int type); +int alloc_page_type(struct pfn_info *page, unsigned long type); +void free_page_type(struct pfn_info *page, unsigned long type); extern void invalidate_shadow_ldt(struct vcpu *d); extern int shadow_remove_all_write_access( struct domain *d, unsigned long gpfn, unsigned long gmfn); @@ -183,7 +199,7 @@ static inline int get_page(struct pfn_info *page, unlikely(d != _domain) ) /* Wrong owner? */ { if ( !_shadow_mode_refcounts(domain) ) - DPRINTK("Error pfn %lx: rd=%p, od=%p, caf=%08x, taf=%08x\n", + DPRINTK("Error pfn %lx: rd=%p, od=%p, caf=%08x, taf=%" PRtype_info "\n", page_to_pfn(page), domain, unpickle_domptr(d), x, page->u.inuse.type_info); return 0; @@ -200,7 +216,7 @@ static inline int get_page(struct pfn_info *page, } void put_page_type(struct pfn_info *page); -int get_page_type(struct pfn_info *page, u32 type); +int get_page_type(struct pfn_info *page, unsigned long type); int get_page_from_l1e(l1_pgentry_t l1e, struct domain *d); void put_page_from_l1e(l1_pgentry_t l1e, struct domain *d); @@ -213,7 +229,7 @@ static inline void put_page_and_type(struct pfn_info *page) static inline int get_page_and_type(struct pfn_info *page, struct domain *domain, - u32 type) + unsigned long type) { int rc = get_page(page, domain); diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h index b44ac07b60..b7195f0209 100644 --- a/xen/include/asm-x86/page.h +++ b/xen/include/asm-x86/page.h @@ -208,20 +208,21 @@ typedef struct { u64 pfn; } pagetable_t; + DOMAIN_ENTRIES_PER_L4_PAGETABLE) #endif -#define linear_l1_table \ +#define VA_LINEAR_PT_VIRT_START (LINEAR_PT_VIRT_START & VADDR_MASK) +#define linear_l1_table \ ((l1_pgentry_t *)(LINEAR_PT_VIRT_START)) -#define __linear_l2_table \ - ((l2_pgentry_t *)(LINEAR_PT_VIRT_START + \ - (LINEAR_PT_VIRT_START >> (PAGETABLE_ORDER<<0)))) -#define __linear_l3_table \ - ((l3_pgentry_t *)(LINEAR_PT_VIRT_START + \ - (LINEAR_PT_VIRT_START >> (PAGETABLE_ORDER<<0)) + \ - (LINEAR_PT_VIRT_START >> (PAGETABLE_ORDER<<1)))) -#define __linear_l4_table \ - ((l4_pgentry_t *)(LINEAR_PT_VIRT_START + \ - (LINEAR_PT_VIRT_START >> (PAGETABLE_ORDER<<0)) + \ - (LINEAR_PT_VIRT_START >> (PAGETABLE_ORDER<<1)) + \ - (LINEAR_PT_VIRT_START >> (PAGETABLE_ORDER<<2)))) +#define __linear_l2_table \ + ((l2_pgentry_t *)(LINEAR_PT_VIRT_START + \ + (VA_LINEAR_PT_VIRT_START >> (PAGETABLE_ORDER<<0)))) +#define __linear_l3_table \ + ((l3_pgentry_t *)(LINEAR_PT_VIRT_START + \ + (VA_LINEAR_PT_VIRT_START >> (PAGETABLE_ORDER<<0)) + \ + (VA_LINEAR_PT_VIRT_START >> (PAGETABLE_ORDER<<1)))) +#define __linear_l4_table \ + ((l4_pgentry_t *)(LINEAR_PT_VIRT_START + \ + (VA_LINEAR_PT_VIRT_START >> (PAGETABLE_ORDER<<0)) + \ + (VA_LINEAR_PT_VIRT_START >> (PAGETABLE_ORDER<<1)) + \ + (VA_LINEAR_PT_VIRT_START >> (PAGETABLE_ORDER<<2)))) #define linear_pg_table linear_l1_table #define linear_l2_table(_ed) ((_ed)->arch.guest_vtable) diff --git a/xen/include/asm-x86/shadow.h b/xen/include/asm-x86/shadow.h index 399d1d6371..955d323d05 100644 --- a/xen/include/asm-x86/shadow.h +++ b/xen/include/asm-x86/shadow.h @@ -485,7 +485,7 @@ static inline int __mark_dirty(struct domain *d, unsigned int mfn) { SH_LOG("mark_dirty OOR! mfn=%x pfn=%lx max=%x (dom %p)", mfn, pfn, d->arch.shadow_dirty_bitmap_size, d); - SH_LOG("dom=%p caf=%08x taf=%08x", + SH_LOG("dom=%p caf=%08x taf=%" PRtype_info, page_get_owner(&frame_table[mfn]), frame_table[mfn].count_info, frame_table[mfn].u.inuse.type_info ); @@ -602,14 +602,14 @@ static inline void shadow_drop_references( /* XXX This needs more thought... */ printk("%s: needing to call shadow_remove_all_access for mfn=%lx\n", __func__, page_to_pfn(page)); - printk("Before: mfn=%lx c=%08x t=%08x\n", page_to_pfn(page), + printk("Before: mfn=%lx c=%08x t=%" PRtype_info "\n", page_to_pfn(page), page->count_info, page->u.inuse.type_info); shadow_lock(d); shadow_remove_all_access(d, page_to_pfn(page)); shadow_unlock(d); - printk("After: mfn=%lx c=%08x t=%08x\n", page_to_pfn(page), + printk("After: mfn=%lx c=%08x t=%" PRtype_info "\n", page_to_pfn(page), page->count_info, page->u.inuse.type_info); } @@ -648,7 +648,7 @@ get_shadow_ref(unsigned long smfn) if ( unlikely(nx == 0) ) { - printk("get_shadow_ref overflow, gmfn=%x smfn=%lx\n", + printk("get_shadow_ref overflow, gmfn=%" PRtype_info " smfn=%lx\n", frame_table[smfn].u.inuse.type_info & PGT_mfn_mask, smfn); BUG(); @@ -678,7 +678,8 @@ put_shadow_ref(unsigned long smfn) if ( unlikely(x == 0) ) { - printk("put_shadow_ref underflow, smfn=%lx oc=%08x t=%08x\n", + printk("put_shadow_ref underflow, smfn=%lx oc=%08x t=%" + PRtype_info "\n", smfn, frame_table[smfn].count_info, frame_table[smfn].u.inuse.type_info); @@ -1200,7 +1201,7 @@ static inline unsigned long __shadow_status( #ifndef NDEBUG if ( ___shadow_status(d, gpfn, stype) != 0 ) { - printk("d->id=%d gpfn=%lx gmfn=%lx stype=%lx c=%x t=%x " + printk("d->id=%d gpfn=%lx gmfn=%lx stype=%lx c=%x t=%" PRtype_info " " "mfn_out_of_sync(gmfn)=%d mfn_is_page_table(gmfn)=%d\n", d->domain_id, gpfn, gmfn, stype, frame_table[gmfn].count_info, diff --git a/xen/include/asm-x86/x86_64/page.h b/xen/include/asm-x86/x86_64/page.h index eeafe4fea5..322ba03c0a 100644 --- a/xen/include/asm-x86/x86_64/page.h +++ b/xen/include/asm-x86/x86_64/page.h @@ -42,7 +42,8 @@ typedef l4_pgentry_t root_pgentry_t; #endif /* !__ASSEMBLY__ */ /* Given a virtual address, get an entry offset into a linear page table. */ -#define l1_linear_offset(_a) (((_a) & VADDR_MASK) >> PAGE_SHIFT) +#define l1_linear_offset(_a) (((_a) & VADDR_MASK) >> L1_PAGETABLE_SHIFT) +#define l2_linear_offset(_a) (((_a) & VADDR_MASK) >> L2_PAGETABLE_SHIFT) #define is_guest_l1_slot(_s) (1) #define is_guest_l2_slot(_t, _s) (1) -- 2.30.2